window.onload = () => {
    const VSHADER_SOURCE = `
    attribute vec4 a_Position;
    attribute float a_PointSize;
    void main(){
      gl_Position = a_Position;
      gl_PointSize =a_PointSize;
    }`;

    const FSHADER_SOURCE = `
    precision mediump float;
    uniform vec4 u_FragColor;
    uniform bool flag;
    void main(){
        if(flag){
            float dist =distance(gl_PointCoord,vec2(0.5,0.5));
            if(dist<0.5){
                gl_FragColor = u_FragColor;
            }else{
                discard;
            }
        }else{
            gl_FragColor = u_FragColor;
        }
    }`;
    const canvas = document.getElementById('webgl');
    const gl = getWebGLContext(canvas);
    if (!gl) {
        console.log('Fail');
        return;
    }
    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        console.log('Failed');
        return;
    }

    let a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    let u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
    let flag = gl.getUniformLocation(gl.program, 'flag');
    let a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');

    const translationPosition = (x1, y1, x2, y2, lineWidthHalf) => {
        let vectorXab = x2 - x1;
        let vectorYab = y2 - y1;
        let temp = lineWidthHalf * vectorXab / Math.sqrt(vectorYab * vectorYab + vectorXab * vectorXab);

        let ya1 = y1 + temp;
        let xa1 = vectorXab === 0 ? x1 - lineWidthHalf : x1 - vectorYab * (ya1 - y1) / vectorXab;
        let ya2 = y1 - temp;
        let xa2 = vectorXab === 0 ? x1 + lineWidthHalf : x1 - vectorYab * (ya2 - y1) / vectorXab;

        let xb1 = xa1 + vectorXab;
        let xb2 = xa2 + vectorXab;
        let yb1 = ya1 + vectorYab;
        let yb2 = ya2 + vectorYab;
        return [xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2];
    };

    const pointsTranslationPosition = (array, formerLineWidth, offsetIndex = 0) => {
        let lineWidth = 0.5 * formerLineWidth;
        let ArrayData = [];
        let ArrayIndex = [];
        let newArray = [];
        let index = [];
        for (let i = 0, length = array.length; i < length - 2; i += 2) {
            if (newArray.length > 2000) {
                ArrayData = ArrayData.concat(newArray);
                newArray = [];
            }
            if (index.length > 2000) {
                ArrayIndex = ArrayIndex.concat(index);
                index = [];
            }

            let [x1, y1, x2, y2] = [array[i], array[i + 1], array[i + 2], array[i + 3]];
            newArray = newArray.concat(translationPosition(x1, y1, x2, y2, lineWidth));
            let temp = (ArrayData.length + newArray.length) / 2 + offsetIndex;
            index.push(temp - 4, temp - 3, temp - 2, temp - 3, temp - 2, temp - 1);
        }

        ArrayData = ArrayData.concat(newArray);
        ArrayIndex = ArrayIndex.concat(index);

        return {
            ArrayData: ArrayData,
            ArrayIndex: ArrayIndex
        };
    }

    let data = [];

    let lineNumber = 3000;
    for (let i = 0; i < lineNumber; i++) {
        let data2 = [];
        for (let j = 0; j < 6; j++) {
            if (Math.random() < 0.5) {
                data2.push((-1) * Math.random());
            } else {
                data2.push(Math.random());
            }
        }
        data.push(data2);
    }

    const drawLines = (lineWidth, offsetIndex = 0) => {
        let ArrayData = [];
        let ArrayIndex = [];
        let newData = [];
        let index = [];
        let ArrayOriginIndex = [];
        let originIndex = [];
        for (let i = 0; i < lineNumber; i++) {
            let data2 = data[i];
            let obj = pointsTranslationPosition(data2, lineWidth, (offsetIndex + ArrayData.length + newData.length) / 2);
            if (newData.length > 2000) {
                ArrayData = ArrayData.concat(newData);
                newData = [];
            }
            if (index.length > 2000) {
                ArrayIndex = ArrayIndex.concat(index);
                index = [];
            }
            newData = newData.concat(obj.ArrayData);
            index = index.concat(obj.ArrayIndex);
        }
        ArrayData = ArrayData.concat(newData);
        ArrayIndex = ArrayIndex.concat(index);

        let now = new Date().getTime();
        let t = 0;
        let count = 0;
        let tempArray = [];
        for (let j = 0; j < lineNumber; j++) {
            if (tempArray.length > 2000) {
                ArrayData = ArrayData.concat(tempArray);
                tempArray = [];
            }

            for (let i = 0, length = data[j].length; i < length; i += 2) {
                if (originIndex.length > 2000) {
                    ArrayOriginIndex = ArrayOriginIndex.concat(originIndex);
                    originIndex = [];
                }
                let temp = (offsetIndex + ArrayData.length + tempArray.length + i) / 2;
                originIndex.push(temp);
            }
            tempArray = tempArray.concat(data[j]);
        }
        ArrayData = ArrayData.concat(tempArray);
        let Indexlength = ArrayIndex.length;
        ArrayIndex = ArrayIndex.concat(ArrayOriginIndex, originIndex);
        return {
            ArrayData,
            ArrayIndex,
            Indexlength
        };
    }

    let canvasWidth = canvas.offsetWidth;
    let tempObj = drawLines(20.0 / canvasWidth);
    let tempObj1 = drawLines(15.0 / canvasWidth, tempObj.ArrayData.length);
    let vertices = new Float32Array(tempObj.ArrayData.concat(tempObj1.ArrayData));
    let index = tempObj.ArrayIndex.concat(tempObj1.ArrayIndex);
    let IndexLength = tempObj.Indexlength;

    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(index), gl.STATIC_DRAW);

    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.uniform4f(u_FragColor, ...[0.0, 1.0, 0.0, 1.0]);

    gl.uniform1f(flag, false);
    gl.drawElements(gl.TRIANGLES, IndexLength, gl.UNSIGNED_SHORT, 0);

    gl.uniform1f(flag, true);
    gl.vertexAttrib1f(a_PointSize, 10.0);
    gl.uniform4f(u_FragColor, ...[1.0, 1.0, 0.0, 1.0]);
    gl.drawElements(gl.POINTS, index.length * 0.5 - IndexLength, gl.UNSIGNED_SHORT, IndexLength * 2);

    gl.uniform4f(u_FragColor, ...[0.0, 0.0, 1.0, 1.0]);
    gl.uniform1f(flag, false);
    gl.drawElements(gl.TRIANGLES, IndexLength, gl.UNSIGNED_SHORT, index.length);

    gl.uniform1f(flag, true);
    gl.vertexAttrib1f(a_PointSize, 8.0);
    gl.uniform4f(u_FragColor, ...[0.0, 0.0, 1.0, 1.0]);
    gl.drawElements(gl.POINTS, index.length * 0.5 - IndexLength, gl.UNSIGNED_SHORT, index.length + IndexLength * 2);
};